package com.zijin.utils;


import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.annotation.PostConstruct;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.util.Properties;

/**
 * JavaMail工具类，用于在Java中发送邮件
 *
 * @author hudy
 *  2024/9/14 13:41
 */
//这里打上这个是为了让它能够注入参数，而不是做为Bean去使用
@Slf4j
@Component
@SuppressWarnings("unused")
public class EmailSenderUtil {


    /**
     * 邮箱发送账号
     */
    public static String USERNAME = "hello@gmail.com";

    /**
     * 邮箱平台的授权码
     */
    public static String PASSWORD = "your password";
    /**
     * SMTP服务器地址
     */
    public static String HOST = "smtp.gmail.com";

    /**
     * SMTP服务器端口
     */
    public static String PORT = "587";

    //上面的参数是为了方便你观看的，正常启动会被覆盖掉的


    @PostConstruct
    public void init(){

        log.info("邮件工具开始初始化~");
        USERNAME = this.MyUSERNAME;
        PASSWORD = this.MyPASSWORD;
        HOST = this.MyHOST;
        PORT = this.MyPORT;
        log.info("邮件工具初始化完成，注入参数username:{},password:{},host:{},port:{}",USERNAME,PASSWORD,HOST,PORT);

    }

    @Value("${zijin.email.user_name}")
    private String MyUSERNAME;


    @Value("${zijin.email.password}")
    private  String MyPASSWORD;

    @Value("${zijin.email.host}")
    private String MyHOST;


    @Value("${zijin.email.port}")
    private String MyPORT;

    public static Session session = null;



    /**
     * 创建邮件会话
     * <p>
     * 本方法用于初始化一个邮件会话(session)，该会话配置了必要的属性以支持通过SMTP发送邮件 如果session已经初始化，则方法直接返回不做任何操作
     */
    public static void createMailSession() {
        if (session != null) {
            return;
        }

        // 设置邮件会话属性
        final Properties props = getProperties();

        // 创建邮件会话实例
        session = Session.getInstance(props,
                new javax.mail.Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(USERNAME, PASSWORD);
                    }
                });
    }

    @NotNull
    private static Properties getProperties() {
        Properties props = new Properties();
        // 启用SMTP身份验证
        props.put("mail.smtp.auth", "true");
        // 启用STARTTLS加密 587端口
        props.put("mail.smtp.starttls.enable", "true");
        // 设置SMTP主机
        props.put("mail.smtp.host", HOST);
        // 设置SMTP端口
        props.put("mail.smtp.port", PORT);
        if ("465".equals(PORT)) {
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.smtp.socketFactory.fallback", "false");
            props.put("mail.smtp.socketFactory.port", "465");
        }
        return props;
    }

    /**
     * 发送纯文本邮件
     *
     * @param title   邮件标题
     * @param content 邮件内容
     * @param toMail  收件人邮箱地址
     */
    public static void postMessage(String title, String content, String toMail) {
        log.info("参数username:{},password:{},host:{},port:{},向{}发送邮件",USERNAME,PASSWORD,HOST,PORT,toMail);
        try {
            createMailSession();
            //构造邮件主体
            MimeMessage message = new MimeMessage(session);
            message.setSubject(title);
            message.setText(content);
            message.setFrom(new InternetAddress(USERNAME));
            String[] recipients = toMail.split(",");
            for (String recipient : recipients) {
                message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress(recipient.trim()));
            }
            //发送
            Transport.send(message);
        } catch (MessagingException e) {
            if (e.getMessage().contains("554 Reject by")) {
                log.error("发信行为被反垃圾拦截，投递失败。");
                throw new RuntimeException("发信行为被反垃圾拦截，投递失败。");
            }
            throw new RuntimeException(e);
        }
    }

    /**
     * 发送带附件的邮件
     * <p>
     * 此方法用于发送一封带有附件的邮件，它首先创建邮件会话，然后构造邮件主体和附件，并发送邮件
     *
     * @param title       邮件标题
     * @param htmlContent 邮件内容，支持HTML格式
     * @param filePath    附件文件路径
     * @param toMail      收件人邮箱地址
     */
    public static void postMessageWithFile(String title, String htmlContent, String filePath, String toMail) {

        try {
            // 创建邮件会话
            createMailSession();

            // 构造邮件主体
            MimeMessage message = new MimeMessage(session);
            message.setSubject(title);

            // 设置邮件正文为HTML格式
            BodyPart textPart = new MimeBodyPart();
            textPart.setContent(htmlContent, "text/html;charset=utf-8");

            // 设置邮件附件
            BodyPart filePart = new MimeBodyPart();
            DataSource source = new FileDataSource(filePath);
            filePart.setFileName(new File(filePath).getName());
            filePart.setDataHandler(new DataHandler(source));

            // 将邮件正文和附件组合到多部分对象中
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(textPart);
            multipart.addBodyPart(filePart);
            message.setContent(multipart);

            // 设置发件人和收件人
            message.setFrom(new InternetAddress(USERNAME));
            String[] recipients = toMail.split(",");
            for (String recipient : recipients) {
                message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress(recipient.trim()));
            }
            // 发送邮件
            Transport.send(message);
        } catch (Exception e) {
            // 如果有异常抛出，转换为运行时异常
            if (e.getMessage().contains("554 Reject by")) {
                log.error("发信行为被反垃圾拦截，投递失败。");
                throw new RuntimeException("发信行为被反垃圾拦截，投递失败。");
            }
            throw new RuntimeException(e);
        }
    }
}
